using System;
using System.Data;
using System.Reflection;
using System.Collections.Generic;

namespace Publish.Utility
{
    /// <summary>
    /// DataTable与实体类互相转换
    /// </summary>
    /// <typeparam name="T">实体类</typeparam>
    public class ModelHandler<T> where T : new()
    {
        #region DataTable转换成实体类

        /// <summary>
        /// 填充对象列表：用DataSet的第一个表填充实体类
        /// </summary>
        /// <param name="ds">DataSet</param>
        /// <returns></returns>
        public IList<T> FillModel(DataSet ds)
        {
            if (ds == null || ds.Tables[0] == null || ds.Tables[0].Rows.Count == 0)
            {
                return null;
            }

            return FillModel(ds.Tables[0]);
        }

        /// <summary> 
        /// 填充对象列表：用DataSet的第index个表填充实体类
        /// </summary> 
        public IList<T> FillModel(DataSet ds, int index)
        {
            if (ds == null || ds.Tables.Count <= index || ds.Tables[index].Rows.Count == 0)
            {
                return null;
            }

            return FillModel(ds.Tables[index]);
        }

        /// <summary> 
        /// 填充对象列表：用DataTable填充实体类
        /// </summary> 
        public IList<T> FillModel(DataTable dt)
        {
            if (dt == null || dt.Rows.Count == 0)
            {
                return new List<T>();
            }
            List<T> modelList = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                //T model = (T)Activator.CreateInstance(typeof(T)); 
                T model = new T();
                for (var i = 0; i < dr.Table.Columns.Count; i++)
                {
                    var column = dr.Table.Columns[i];
                    var columnName = column.ColumnName;

                    PropertyInfo propertyInfo = model.GetType().GetProperty(columnName);
                    
                    if (propertyInfo == null) continue;

                    var type = propertyInfo.PropertyType.Name;

                    switch (type)
                    {
                        //case "Guid":
                        //    propertyInfo.SetValue(model, dr[i].ToString().ToGuid(Guid.Empty), null);
                        //    break;
                        default:
                            propertyInfo.SetValue(model, dr[i], null);
                            break;
                    }
                }

                modelList.Add(model);
            }
            return modelList;
        }

        /// <summary> 
        /// 填充对象：用DataRow填充实体类
        /// </summary> 
        public T FillModel(DataRow dr)
        {
            if (dr == null)
            {
                return default(T);
            }

            T model = new T();

            for (int i = 0; i < dr.Table.Columns.Count; i++)
            {
                var column = dr.Table.Columns[i];
                var columnName = column.ColumnName;
                PropertyInfo propertyInfo = model.GetType().GetProperty(columnName);

                if (propertyInfo == null) continue;

                var type = propertyInfo.PropertyType.Name;

                switch (type)
                {
                    //case "Guid":
                    //propertyInfo.SetValue(model, dr[i].ToString().ToGuid(Guid.Empty), null);
                    //break;
                    default:
                        propertyInfo.SetValue(model, dr[i], null);
                        break;
                }
            }
            return model;

            //T model = new T();
            //var column = dr.Table.Columns[i];
            //var columnName = column.ColumnName;

            //PropertyInfo propertyInfo = model.GetType().GetProperty(columnName);

            //var type = propertyInfo.PropertyType.Name;

            //switch (type)
            //{
            //    case "Guid":
            //        propertyInfo.SetValue(model, dr[i].ToString().ToGuid(Guid.Empty), null);
            //        break;
            //    default:
            //        propertyInfo.SetValue(model, dr[i], null);
            //        break;
            //}
            //return model;
        }

        #endregion

        #region 实体类转换成DataTable

        /// <summary>
        /// 实体类转换成DataSet
        /// </summary>
        /// <param name="modelList">实体类列表</param>
        /// <returns></returns>
        public DataSet FillDataSet(List<T> modelList)
        {
            if (modelList == null || modelList.Count == 0)
            {
                return null;
            }
            DataSet ds = new DataSet();
            ds.Tables.Add(FillDataTable(modelList));
            return ds;
        }

        /// <summary>
        /// 实体类转换成DataTable
        /// </summary>
        /// <param name="modelList">实体类列表</param>
        /// <returns></returns>
        public DataTable FillDataTable(List<T> modelList)
        {
            if (modelList == null || modelList.Count == 0)
            {
                return null;
            }
            DataTable dt = CreateData(modelList[0]);

            foreach (T model in modelList)
            {
                DataRow dataRow = dt.NewRow();
                foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
                {
                    dataRow[propertyInfo.Name] = propertyInfo.GetValue(model, null);
                }
                dt.Rows.Add(dataRow);
            }
            return dt;
        }

        /// <summary>
        /// 根据实体类得到表结构
        /// </summary>
        /// <param name="model">实体类</param>
        /// <returns></returns>
        private DataTable CreateData(T model)
        {
            DataTable dataTable = new DataTable(typeof(T).Name);
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                dataTable.Columns.Add(new DataColumn(propertyInfo.Name, propertyInfo.PropertyType));
            }
            return dataTable;
        }

        #endregion

        #region DataTable转换成JSON

        ///// <summary>
        ///// 将DataSet 转换为Json
        ///// </summary>
        ///// <param name="dt">DataTable</param>
        ///// <returns></returns>
        //public String ToJson(DataTable dt)
        //{
        //    return dt == null || dt.Rows.Count == 0 
        //        ? String.Empty 
        //        : Newtonsoft.Json.JsonConvert.SerializeObject(dt);
        //}

        #endregion
    }
}
